package com.zjc;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.SecureClassLoader;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

public class CustomSecureClassLoader extends SecureClassLoader {

    private Map<String, Class<?>> classByteMap = new HashMap<>();

    public CustomSecureClassLoader(ClassLoader parent) throws IOException {
        super(parent);
    }


    public void load(String jarPath) throws IOException {
        /**
         * 网络jar包
         */
//        try {
//            URI uri = new URI(jarPath);
//            URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
//            Method add = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
//            add.setAccessible(true);
//            add.invoke(classLoader, uri.toURL());
//        } catch (Exception exp) {
//            exp.printStackTrace();
//        }
//
//        Class<?> r = Class.forName("com.zjc.Reflex");


        /**
         * 本地jar包
         */
        JarInputStream jarInputStream = new JarInputStream(Files.newInputStream(Paths.get(jarPath)));

        JarEntry jarEntry = jarInputStream.getNextJarEntry();
        while (jarEntry != null) {
            String name = jarEntry.getName();
            if (name.endsWith(".class")) {
                byte[] buffer = new byte[1024 * 1024];
                String className = name.replaceAll("/", ".").replaceAll(".class", "");
                int size = 0, read;
                while (true) {
                    read = jarInputStream.read(buffer, size, 256);
                    if (read == -1) {
                        break;
                    }
                    size += read;
                }
                byte[] classBytes = new byte[size];
                System.arraycopy(buffer, 0, classBytes, 0, size);

                Class<?> c = super.defineClass(className, classBytes, 0, classBytes.length);
                classByteMap.put(className, c);
            }

            jarEntry = jarInputStream.getNextJarEntry();
        }
    }

    @Override
    protected Class<?> findClass(String name) {
        return classByteMap.get(name);
    }
}
